package szoftlab4;

import java.util.*;

/**
 * Asztal, ahol különböző építőelemek helyezkednek el és kapcsolódnak egymáshoz.
 * Saját ütemezője van, amellyel a hálózat jelterjedését szimulálja.
 * @author Peti
 */
@SuppressWarnings("LeakingThisInConstructor")
public class Asztal
{

    private boolean fut;
    private int periodusido;

    /**
     * Az építőelemek ezen az asztalon belül.
     */
    protected ArrayList<Epitoelem> elemek = new ArrayList<Epitoelem>();

    /**
     * Tartalmazza egy stabilizációs cikluson belül az összes eddigi állapotot
     * a ki- és bemeneteken.
     */
    protected ArrayList<ArrayList<Boolean>> allapot = new ArrayList<ArrayList<Boolean>>();

    /**
     * A megváltozott, és még fel nem dolgozott bemenetek.
     */
    protected LinkedList<Bemenet> esemenysor = new LinkedList<Bemenet>();

    /**
     * Az építőelemeket léptető visitor.
     */
    protected LeptetoEpitoelemAktivVisitor lepteto;

    /**
     * Az építőelemeket visszaállító visitor.
     */
    protected VisszaallitoEpitoelemAktivVisitor visszaallito;

    /**
     * Ha nem üres az eseménysor, akkor az első eleméhez elvégzi a szükséges lépéseket:
     * meghívja az adott bemenet getSzulo függvényét, majd az épitőeleméhez tartozó szamol függvényt.
     */
    protected void sortKiertekel()
    {
        Logger.log(this, HivasTipus.Call, "Asztal", "void sortKiertekel()");
        try
        {
            if (Logger.igenloValasz("Van még elem az eseménysorban?"))
            {
                if (!Logger.igenloValasz("Ismétlődik a hálózat állapota?"))
                {
                    ((Bemenet) Logger.objektumvalasztas("Melyik sorszámú objektum a soron következő bemenet az eseménysorban?")).getSzulo().szamol();
                }
                else
                {
                    megallit();
                }
            }
        } catch (Exception e)
        {
        }

        Logger.log(this, HivasTipus.Return, "Asztal", "void sortKiertekel()");
    }

    /**
     * Az asztal konstruktora.
     * Az s bemenete alapján létrehozza a hálózathoz szükséges elemeket, és elvégzi
     * a szükséges építőelemek összekötését.
     *
     * @param s
     * A hálózat létrehozásához szükséges adatokat tartalmazó String
     * (építőelemek és csatlakozásaik).
     */
    public Asztal(String s)
    {
        Logger.log(this, HivasTipus.Create, "Asztal", "Asztal()");
        lepteto = new LeptetoEpitoelemAktivVisitor();
        visszaallito = new VisszaallitoEpitoelemAktivVisitor();
        /* Szkeleton tesztesetei
         *
        if (s.compareTo("1") == 0)
        {
            teszteset1();
        }
        if (s.compareTo("2") == 0)
        {
            teszteset2();
        }
        if (s.compareTo("3") == 0)
        {
            teszteset3();
        }
        if (s.compareTo("4") == 0)
        {
            teszteset4();
        }
         *
         */
        Logger.log(this, HivasTipus.Return, "Asztal", "Asztal()");
    }

    /**
     * Beállítja a periódusidőt a megadott értékre.
     *
     * @param periodusido
     * A megadott periódusidő másodpercekben.
     */
    public void setPeriodusido(int periodusido)
    {
        Logger.log(this, HivasTipus.Call, "Asztal", "void setPeriodusido()");
        Logger.log(this, HivasTipus.Return, "Asztal", "void setPeriodusido()");
    }

    /**
     * Visszaadja a periódusidőt
     *
     * @return periodusido
     * A periódusidő másodpercekben.
     */
    public int getPeriodusido()
    {
        Logger.log(this, HivasTipus.Call, "Asztal", "int getPeriodusido()");
        Logger.log(this, HivasTipus.Return, "Asztal", "int getPeriodusido()");
        return 0;
    }

    /**
     * Megállítja a szimulációt.
     */
    public void megallit()
    {
        Logger.log(this, HivasTipus.Call, "Asztal", "void megallit()");
        Logger.log(this, HivasTipus.Return, "Asztal", "void megallit()");
    }

    /**
     * Elindítja a szimulációt.
     */
    public void elindit()
    {
        Logger.log(this, HivasTipus.Call, "Asztal", "void elindit()");
        for (Epitoelem e : elemek)
        {
            e.accept(visszaallito);
        }
        try
        {
            while (Logger.igenloValasz("Léptessünk?"))
            {
                for (Epitoelem e : elemek)
                {
                    e.accept(lepteto);
                }
            }
        } catch (Exception e)
        {
        }
        Logger.log(this, HivasTipus.Return, "Asztal", "void elindit()");
    }

    /**
     * Beteszi az eseménysorba a megadott bemenetet, hogy később kiértékelhesse a változását.
     *
     * @param b
     * A sorba felveendő bemenet.
     */
    public void sorbaFelvesz(Bemenet b)
    {
        Logger.log(this, HivasTipus.Call, "Asztal", "void sorbaFelvesz()");
        Logger.log(this, HivasTipus.Return, "Asztal", "void sorbaFelvesz()");
    }

    /* Szkeleton tesztesetei
     *
    private void teszteset1()
    {
        elemek.add(new Kapcsolo());
        elemek.add(new Vezetek());
        elemek.add(new Lampa());
        elemek.get(1).csatlakozik(0, elemek.get(0), 0);
        elemek.get(2).csatlakozik(0, elemek.get(1), 0);
    }

    private void teszteset2()
    {
        elemek.add(new Kapcsolo());
        elemek.add(new Kapcsolo());
        elemek.add(new Vezetek());
        elemek.add(new Vezetek());
        elemek.add(new EsKapu());
        elemek.add(new Vezetek());
        elemek.add(new Lampa());
        Logger.engedelyezve(true);
        try
        {
            while (Logger.igenloValasz("Kell még az eseménysort kiértékelni?"))
            {
                sortKiertekel();
            }
        } catch (Exception e)
        {
        }
        Logger.engedelyezve(false);
    }

    private void teszteset3()
    {
        elemek.add(new Jelgenerator());
        elemek.add(new Vezetek());
        elemek.add(new Lampa());
        Logger.engedelyezve(true);
        ((Jelgenerator) elemek.get(0)).setSorozat(null);
        setPeriodusido(0);
        elindit();
        Logger.engedelyezve(false);
    }

    private void teszteset4()
    {
        elemek.add(new Kapcsolo());
        elemek.add(new Vezetek());
        Logger.engedelyezve(true);
        try
        {
            while (Logger.igenloValasz("Kapcsoljunk?"))
            {
                ((Kapcsolo) elemek.get(0)).kapcsol();
            }
        } catch (Exception e)
        {
        }
        Logger.engedelyezve(false);
    }
     *
     */
}
